home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 April / PCWorld_2008-04_cd.bin / v cisle / ozo / zotero-1.0.3.xpi / chrome / zotero.jar / content / zotero / fileInterface.js < prev    next >
Encoding:
JavaScript  |  2008-01-14  |  17.8 KB  |  574 lines

  1. /*
  2.     ***** BEGIN LICENSE BLOCK *****
  3.     
  4.     Copyright (c) 2006  Center for History and New Media
  5.                         George Mason University, Fairfax, Virginia, USA
  6.                         http://chnm.gmu.edu
  7.     
  8.     Licensed under the Educational Community License, Version 1.0 (the "License");
  9.     you may not use this file except in compliance with the License.
  10.     You may obtain a copy of the License at
  11.     
  12.     http://www.opensource.org/licenses/ecl1.php
  13.     
  14.     Unless required by applicable law or agreed to in writing, software
  15.     distributed under the License is distributed on an "AS IS" BASIS,
  16.     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17.     See the License for the specific language governing permissions and
  18.     limitations under the License.
  19.     
  20.     ***** END LICENSE BLOCK *****
  21. */
  22.  
  23. /****Zotero_File_Exporter****
  24.  **
  25.  * A class to handle exporting of items, collections, or the entire library
  26.  **/
  27.  
  28. /**
  29.  * Constructs a new Zotero_File_Exporter with defaults
  30.  **/
  31. var Zotero_File_Exporter = function() {
  32.     this.name = Zotero.getString("fileInterface.exportedItems");
  33.     this.collection = false;
  34.     this.items = false;
  35. }
  36.  
  37. /**
  38.  * Performs the actual export operation
  39.  **/
  40. Zotero_File_Exporter.prototype.save = function() {
  41.     var translation = new Zotero.Translate("export");
  42.     var translators = translation.getTranslators();
  43.     
  44.     // present options dialog
  45.     var io = {translators:translators}
  46.     window.openDialog("chrome://zotero/content/exportOptions.xul",
  47.         "_blank", "chrome,modal,centerscreen", io);
  48.     if(!io.selectedTranslator) {
  49.         return false;
  50.     }
  51.     
  52.     const nsIFilePicker = Components.interfaces.nsIFilePicker;
  53.     var fp = Components.classes["@mozilla.org/filepicker;1"]
  54.             .createInstance(nsIFilePicker);
  55.     fp.init(window, Zotero.getString("fileInterface.export"), nsIFilePicker.modeSave);
  56.     
  57.     // set file name and extension
  58.     if(io.selectedTranslator.displayOptions.exportFileData) {
  59.         // if the result will be a folder, don't append any extension or use
  60.         // filters
  61.         fp.defaultString = this.name;
  62.         fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
  63.     } else {
  64.         // if the result will be a file, append an extension and use filters
  65.         fp.defaultString = this.name+"."+io.selectedTranslator.target;
  66.         fp.defaultExtension = io.selectedTranslator.target;
  67.         fp.appendFilter(io.selectedTranslator.label, "*."+io.selectedTranslator.target);
  68.     }
  69.     
  70.     var rv = fp.show();
  71.     if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
  72.         if(this.collection) {
  73.             translation.setCollection(this.collection);
  74.         } else if(this.items) {
  75.             translation.setItems(this.items);
  76.         }
  77.         
  78.         translation.setLocation(fp.file);
  79.         translation.setTranslator(io.selectedTranslator);
  80.         translation.setHandler("done", this._exportDone);
  81.         Zotero.UnresponsiveScriptIndicator.disable();
  82.         Zotero_File_Interface.Progress.show(
  83.             Zotero.getString("fileInterface.itemsExported"),
  84.             function() {
  85.                 translation.translate();
  86.         });
  87.     }
  88.     return false;
  89. }
  90.     
  91. /*
  92.  * Closes the items exported indicator
  93.  */
  94. Zotero_File_Exporter.prototype._exportDone = function(obj, worked) {
  95.     Zotero_File_Interface.Progress.close();
  96.     Zotero.UnresponsiveScriptIndicator.enable();
  97.     
  98.     if(!worked) {
  99.         window.alert(Zotero.getString("fileInterface.exportError"));
  100.     }
  101. }
  102.  
  103. /****Zotero_File_Interface****
  104.  **
  105.  * A singleton to interface with ZoteroPane to provide export/bibliography
  106.  * capabilities
  107.  **/
  108. var Zotero_File_Interface = new function() {
  109.     var _importCollection, _unlock;
  110.     
  111.     this.exportFile = exportFile;
  112.     this.exportCollection = exportCollection;
  113.     this.exportItemsToClipboard = exportItemsToClipboard;
  114.     this.exportItems = exportItems;
  115.     this.importFile = importFile;
  116.     this.bibliographyFromCollection = bibliographyFromCollection;
  117.     this.bibliographyFromItems = bibliographyFromItems;
  118.     this.copyItemsToClipboard = copyItemsToClipboard;
  119.     this.copyCitationToClipboard = copyCitationToClipboard;
  120.     
  121.     /*
  122.      * Creates Zotero.Translate instance and shows file picker for file export
  123.      */
  124.     function exportFile() {
  125.         var exporter = new Zotero_File_Exporter();
  126.         exporter.name = Zotero.getString("pane.collections.library");
  127.         exporter.save();
  128.     }
  129.     
  130.     /*
  131.      * exports a collection or saved search
  132.      */
  133.     function exportCollection() {
  134.         var exporter = new Zotero_File_Exporter();
  135.     
  136.         var collection = ZoteroPane.getSelectedCollection();
  137.         if(collection) {
  138.             exporter.name = collection.getName();
  139.             exporter.collection = collection;
  140.         } else {
  141.             // find sorted items
  142.             exporter.items = ZoteroPane.getSortedItems();
  143.             if(!exporter.items) throw ("No items to save");
  144.             
  145.             // find name
  146.             var searchRef = ZoteroPane.getSelectedSavedSearch();
  147.             if(searchRef) {
  148.                 var search = new Zotero.Search();
  149.                 search.load(searchRef['id']);
  150.                 exporter.name = search.getName();
  151.             }
  152.         }
  153.         exporter.save();
  154.     }
  155.     
  156.     
  157.     /*
  158.      * exports items
  159.      */
  160.     function exportItems() {
  161.         var exporter = new Zotero_File_Exporter();
  162.         
  163.         exporter.items = ZoteroPane.getSelectedItems();
  164.         if(!exporter.items || !exporter.items.length) throw("no items currently selected");
  165.         
  166.         exporter.save();
  167.     }
  168.     
  169.     /*
  170.      * exports items to clipboard
  171.      */
  172.     function exportItemsToClipboard(items, translatorID) {
  173.         var translation = new Zotero.Translate("export");
  174.         translation.setItems(items);
  175.         translation.setTranslator(translatorID);
  176.         translation.setHandler("done", _copyToClipboard);
  177.         translation.translate();
  178.     }
  179.     
  180.     /*
  181.      * handler when done exporting items to clipboard
  182.      */
  183.     function _copyToClipboard(obj, worked) {
  184.         if(!worked) {
  185.             window.alert(Zotero.getString("fileInterface.exportError"));
  186.         } else {
  187.             Components.classes["@mozilla.org/widget/clipboardhelper;1"]
  188.                       .getService(Components.interfaces.nsIClipboardHelper)
  189.                       .copyString(obj.output.replace(/\r\n/g, "\n"));
  190.         }
  191.     }
  192.     
  193.     /*
  194.      * Creates Zotero.Translate instance and shows file picker for file import
  195.      */
  196.     function importFile() {
  197.         var translation = new Zotero.Translate("import");
  198.         var translators = translation.getTranslators();
  199.         
  200.         const nsIFilePicker = Components.interfaces.nsIFilePicker;
  201.         var fp = Components.classes["@mozilla.org/filepicker;1"]
  202.                 .createInstance(nsIFilePicker);
  203.         fp.init(window, Zotero.getString("fileInterface.import"), nsIFilePicker.modeOpen);
  204.         
  205.         fp.appendFilters(nsIFilePicker.filterAll);
  206.         for(var i in translators) {
  207.             fp.appendFilter(translators[i].label, "*."+translators[i].target);
  208.         }
  209.         
  210.         var rv = fp.show();
  211.         if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
  212.             translation.setLocation(fp.file);
  213.             // get translators again, bc now we can check against the file
  214.             translators = translation.getTranslators();
  215.             if(translators.length) {
  216.                 // create a new collection to take in imported items
  217.                 var date = new Date();
  218.                 _importCollection = Zotero.Collections.add(Zotero.getString("fileInterface.imported")+" "+date.toLocaleString());
  219.                 
  220.                 // import items
  221.                 translation.setTranslator(translators[0]);
  222.                 translation.setHandler("collectionDone", _importCollectionDone);
  223.                 translation.setHandler("done", _importDone);
  224.                 Zotero.UnresponsiveScriptIndicator.disable();
  225.                 
  226.                 // show progress indicator
  227.                 Zotero_File_Interface.Progress.show(
  228.                     Zotero.getString("fileInterface.itemsImported"),
  229.                     function() {
  230.                         Zotero.DB.beginTransaction();
  231.                         
  232.                         // translate
  233.                         translation.translate();
  234.                 });
  235.             } else {
  236.                 window.alert(Zotero.getString("fileInterface.fileFormatUnsupported"));
  237.             }
  238.         }
  239.     }
  240.     
  241.     /*
  242.      * Saves collections after they've been imported. Input item is of the type
  243.      * outputted by Zotero.Collection.toArray(); only receives top-level
  244.      * collections
  245.      */
  246.     function _importCollectionDone(obj, collection) {
  247.         collection.changeParent(_importCollection.getID());
  248.     }
  249.     
  250.     /*
  251.      * closes items imported indicator
  252.      */
  253.     function _importDone(obj, worked) {
  254.         // add items to import collection
  255.         for each(var itemID in obj.newItems) {
  256.             _importCollection.addItem(itemID);
  257.         }
  258.         
  259.         Zotero.DB.commitTransaction();
  260.         
  261.         Zotero_File_Interface.Progress.close();
  262.         Zotero.UnresponsiveScriptIndicator.enable();
  263.         
  264.         if(!worked) {
  265.             _importCollection.erase();
  266.             window.alert(Zotero.getString("fileInterface.importError"));
  267.         }
  268.     }
  269.     
  270.     /*
  271.      * Creates a bibliography from a collection or saved search
  272.      */
  273.     function bibliographyFromCollection() {
  274.         // find sorted items
  275.         var items = Zotero.Items.get(ZoteroPane.getSortedItems());
  276.         if(!items) return;
  277.         
  278.         // find name
  279.         var name = false;
  280.         
  281.         var collection = ZoteroPane.getSelectedCollection();
  282.         if(collection) {
  283.             name = collection.getName();
  284.         } else {
  285.             var searchRef = ZoteroPane.getSelectedSavedSearch();
  286.             if(searchRef) {
  287.                 var search = new Zotero.Search();
  288.                 search.load(searchRef['id']);
  289.                 name = search.getName();
  290.             }
  291.         }
  292.         
  293.         _doBibliographyOptions(name, items);
  294.         return;
  295.         
  296.         throw ("No collection or saved search currently selected");
  297.     }
  298.     
  299.     /*
  300.      * Creates a bibliography from a items
  301.      */
  302.     function bibliographyFromItems() {
  303.         var items = ZoteroPane.getSelectedItems();
  304.         if(!items || !items.length) throw("no items currently selected");
  305.         
  306.         _doBibliographyOptions(Zotero.getString("fileInterface.untitledBibliography"), items);
  307.     }
  308.     
  309.     
  310.     /*
  311.      * Copies HTML and text bibliography entries for passed items in given style
  312.      *
  313.      * Does not check that items are actual references (and not notes or attachments)
  314.      */
  315.     function copyItemsToClipboard(items, style, asHTML) {
  316.         // copy to clipboard
  317.         var transferable = Components.classes["@mozilla.org/widget/transferable;1"].
  318.                            createInstance(Components.interfaces.nsITransferable);
  319.         var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].
  320.                                getService(Components.interfaces.nsIClipboard);
  321.         var csl = Zotero.Cite.getStyle(style);
  322.         var itemSet = csl.createItemSet(items); 
  323.         
  324.         // add HTML
  325.         var bibliography = csl.formatBibliography(itemSet, "HTML");
  326.         var str = Components.classes["@mozilla.org/supports-string;1"].
  327.                   createInstance(Components.interfaces.nsISupportsString);
  328.         str.data = bibliography;
  329.         transferable.addDataFlavor("text/html");
  330.         transferable.setTransferData("text/html", str, bibliography.length*2);
  331.         
  332.         // add text (or HTML source)
  333.         var bibliography = csl.formatBibliography(itemSet, asHTML ? 'HTML' : 'Text');
  334.         var str = Components.classes["@mozilla.org/supports-string;1"].
  335.                   createInstance(Components.interfaces.nsISupportsString);
  336.         str.data = bibliography;
  337.         transferable.addDataFlavor("text/unicode");
  338.         transferable.setTransferData("text/unicode", str, bibliography.length*2);
  339.         
  340.         clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
  341.     }
  342.     
  343.     
  344.     /*
  345.      * Copies HTML and text citations for passed items in given style
  346.      *
  347.      * Does not check that items are actual references (and not notes or attachments)
  348.      *
  349.      * if |asHTML| is true, copy HTML source as text
  350.      */
  351.     function copyCitationToClipboard(items, style, asHTML) {
  352.         // copy to clipboard
  353.         var transferable = Components.classes["@mozilla.org/widget/transferable;1"].
  354.                            createInstance(Components.interfaces.nsITransferable);
  355.         var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].
  356.                                getService(Components.interfaces.nsIClipboard);
  357.         
  358.         var csl = Zotero.Cite.getStyle(style);
  359.         var itemSet = csl.createItemSet(items);
  360.         var itemIDs = [];
  361.         for (var i=0; i<items.length; i++) {
  362.             itemIDs.push(items[i].getID());
  363.         }
  364.         var citation = csl.createCitation(itemSet.getItemsByIds(itemIDs));
  365.         
  366.         // add HTML
  367.         var bibliography = csl.formatCitation(citation, "HTML");
  368.         var str = Components.classes["@mozilla.org/supports-string;1"].
  369.                   createInstance(Components.interfaces.nsISupportsString);
  370.         str.data = bibliography;
  371.         transferable.addDataFlavor("text/html");
  372.         transferable.setTransferData("text/html", str, bibliography.length*2);
  373.         
  374.         // add text (or HTML source)
  375.         var bibliography = csl.formatCitation(citation, asHTML ? 'HTML' : 'Text');
  376.         var str = Components.classes["@mozilla.org/supports-string;1"].
  377.                   createInstance(Components.interfaces.nsISupportsString);
  378.         str.data = bibliography;
  379.         transferable.addDataFlavor("text/unicode");
  380.         transferable.setTransferData("text/unicode", str, bibliography.length*2);
  381.         
  382.         clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
  383.     }
  384.     
  385.     /*
  386.      * Shows bibliography options and creates a bibliography
  387.      */
  388.     function _doBibliographyOptions(name, items) {
  389.         // make sure at least one item is not a standalone note or attachment
  390.         var haveRegularItem = false;
  391.         for each(var item in items) {
  392.             if (item.isRegularItem()) {
  393.                 haveRegularItem = true;
  394.                 break;
  395.             }
  396.         }
  397.         if (!haveRegularItem) {
  398.             window.alert(Zotero.getString("fileInterface.noReferencesError"));
  399.             return;
  400.         }
  401.         
  402.         var io = new Object();
  403.         var newDialog = window.openDialog("chrome://zotero/content/bibliography.xul",
  404.             "_blank","chrome,modal,centerscreen", io);
  405.         
  406.         if(!io.output) return;
  407.         
  408.         // determine output format
  409.         var format = "HTML";
  410.         if(io.output == "save-as-rtf") {
  411.             format = "RTF";
  412.         }
  413.         
  414.         // generate bibliography
  415.         try {
  416.             if(io.output == 'copy-to-clipboard') {
  417.                 copyItemsToClipboard(items, io.style);
  418.                 return;
  419.             }
  420.             else {
  421.                 var csl = Zotero.Cite.getStyle(io.style);
  422.                 var itemSet = csl.createItemSet(items); 
  423.                 var bibliography = csl.formatBibliography(itemSet, format);
  424.             }
  425.         } catch(e) {
  426.             window.alert(Zotero.getString("fileInterface.bibliographyGenerationError"));
  427.             throw(e);
  428.         }
  429.         
  430.         if(io.output == "print") {
  431.             // printable bibliography, using a hidden browser
  432.             var browser = Zotero.Browser.createHiddenBrowser(window);
  433.             browser.contentDocument.write(bibliography);
  434.             browser.contentDocument.close();
  435.             
  436.             // this is kinda nasty, but we have to temporarily modify the user's
  437.             // settings to eliminate the header and footer. the other way to do
  438.             // this would be to attempt to print with an embedded browser, but
  439.             // it's not even clear how to attempt to create one
  440.             var prefService = Components.classes["@mozilla.org/preferences-service;1"].
  441.                               getService(Components.interfaces.nsIPrefBranch);
  442.             var prefsToClear = ["print.print_headerleft", "print.print_headercenter", 
  443.                                 "print.print_headerright", "print.print_footerleft", 
  444.                                 "print.print_footercenter", "print.print_footerright"];
  445.             var oldPrefs = new Array();
  446.             for(var i in prefsToClear) {
  447.                 oldPrefs[i] = prefService.getCharPref(prefsToClear[i]);
  448.                 prefService.setCharPref(prefsToClear[i], "");
  449.             }
  450.             
  451.             // print
  452.             browser.contentWindow.print();
  453.             
  454.             // set the prefs back
  455.             for(var i in prefsToClear) {
  456.                 prefService.setCharPref(prefsToClear[i], oldPrefs[i]);
  457.             }
  458.             
  459.             Zotero.Browser.deleteHiddenBrowser(browser);
  460.         } else if(io.output == "save-as-html") {
  461.             var fStream = _saveBibliography(name, "HTML");
  462.             
  463.             if(fStream !== false) {            
  464.                 var html = "";
  465.                 html +='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n';
  466.                 html +='<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\n';
  467.                 html +='<head>\n';
  468.                 html +='<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>\n';
  469.                 html +='<title>'+Zotero.getString("fileInterface.bibliographyHTMLTitle")+'</title>\n';
  470.                 html +='</head>\n';
  471.                 html +='<body>\n';
  472.                 html += bibliography;
  473.                 html +='</body>\n';
  474.                 html +='</html>\n';
  475.                 
  476.                 // create UTF-8 output stream
  477.                 var os = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
  478.                          createInstance(Components.interfaces.nsIConverterOutputStream);
  479.                 os.init(fStream, "UTF-8", 0, "?".charCodeAt(0));
  480.  
  481.                 os.writeString(html);
  482.                 
  483.                 os.close();
  484.                 fStream.close();
  485.             }
  486.         } else if(io.output == "save-as-rtf") {
  487.             var fStream = _saveBibliography(name, "RTF");
  488.             if(fStream !== false) {
  489.                 fStream.write(bibliography, bibliography.length);
  490.                 fStream.close();
  491.             }
  492.         }
  493.     }
  494.     
  495.     
  496.     function _saveBibliography(name, format) {    
  497.         // savable bibliography, using a file stream
  498.         const nsIFilePicker = Components.interfaces.nsIFilePicker;
  499.         var fp = Components.classes["@mozilla.org/filepicker;1"]
  500.                 .createInstance(nsIFilePicker);
  501.         fp.init(window, "Save Bibliography", nsIFilePicker.modeSave);
  502.         
  503.         if(format == "RTF") {
  504.             var extension = "rtf";
  505.             fp.appendFilter("RTF", "*.rtf");
  506.         } else {
  507.             var extension = "html";
  508.             fp.appendFilters(nsIFilePicker.filterHTML);
  509.         }
  510.         
  511.         fp.defaultString = name+"."+extension;
  512.         
  513.         var rv = fp.show();
  514.         if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {                
  515.             // open file
  516.             var fStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
  517.                           createInstance(Components.interfaces.nsIFileOutputStream);
  518.             fStream.init(fp.file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
  519.             return fStream;
  520.         } else {
  521.             return false;
  522.         }
  523.     }
  524. }
  525.  
  526. // Handles the display of a progress indicator
  527. Zotero_File_Interface.Progress = new function() {
  528.     var _windowLoaded = false;
  529.     var _windowLoading = false;
  530.     var _progressWindow;
  531.     // keep track of all of these things in case they're called before we're
  532.     // done loading the progress window
  533.     var _loadHeadline, _loadNumber, _outOf, _callback;
  534.     
  535.     this.show = show;
  536.     this.close = close;
  537.     
  538.     function show(headline, callback) {
  539.         if(_windowLoading || _windowLoaded) {    // already loading or loaded
  540.             _progressWindow.focus();
  541.             return false;
  542.         }
  543.         _windowLoading = true;
  544.         
  545.         _loadHeadline = headline;
  546.         _loadNumber = 0;
  547.         _outOf = 0;
  548.         _callback = callback;
  549.         
  550.         _progressWindow = window.openDialog("chrome://zotero/chrome/fileProgress.xul", "", "chrome,resizable=no,close=no,dependent,dialog,centerscreen");
  551.         _progressWindow.addEventListener("pageshow", _onWindowLoaded, false);
  552.         
  553.         return true;
  554.     }
  555.     
  556.     function close() {
  557.         _windowLoaded = false;
  558.         try {
  559.             _progressWindow.close();
  560.         } catch(ex) {}
  561.     }
  562.     
  563.     function _onWindowLoaded() {
  564.         _windowLoading = false;
  565.         _windowLoaded = true;
  566.         
  567.         // do things we delayed because the winodw was loading
  568.         _progressWindow.document.getElementById("progress-label").value = _loadHeadline;
  569.         
  570.         if(_callback) {
  571.             window.setTimeout(_callback, 1500);
  572.         }
  573.     }
  574. }